use anyhow::Result;
use log::{error, info};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tauri_plugin_http::reqwest::Response;

use crate::global;

#[derive(Serialize, Deserialize, Debug)]
struct ResponseData<T> {
    data: Option<T>,
    msg: String,
    code: i32,
    time: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct LoginReq {
    account: String,
    password: String,
    role: u8,
}

#[derive(Deserialize, Debug)]
pub struct BzMessage {
    /// id，需要根据发送情况传给回调接口
    pub id: u32,
    /// 要发送的内容
    pub content: String,
    /// 备注群名
    pub group_name: String,
    /// 群名
    pub group: String,
    create_time_text: String,
}

#[derive(Deserialize, Debug)]
struct BzCallback {
    /// id，需要根据发送情况传给回调接口
    id: u32,
    /// 信息发送结果 "success" || "false"
    result: String,
}

async fn post<T: Serialize>(url: &str, payload: &T) -> Result<Response> {
    let client = crate::get_client();
    let url = format!("http://kefu.shunjicangchu.com{url}");

    let resp = client.post(url).json(payload).send().await?;

    Ok(resp)
}

pub async fn login(account: String, password: String) -> Result<global::BzUser, String> {
    let payload = LoginReq {
        account,
        password,
        role: 2,
    };

    info!("login request: {payload:#?}");

    match post("/mini/user/login", &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<global::BzLogin> = resp.json().await.unwrap();
                if let Some(user) = response.data {
                    global::BZ_USER.get_or_init(|| user.user_info.clone());
                    return Ok(user.user_info);
                } else {
                    return Err(response.msg);
                }
            }
            Err(String::from("request failed"))
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            Err(String::from("request failed"))
        }
    }
}

pub async fn get_send_list() -> Result<Vec<BzMessage>, String> {
    let user = global::BZ_USER.get().unwrap();
    let payload = json!({"token": user.token});

    info!("get send list request: {payload:#?}");

    match post("/mini/send/getSendList", &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<Vec<BzMessage>> = resp.json().await.unwrap();
                if let Some(list) = response.data {
                    return Ok(list);
                } else {
                    return Err(response.msg);
                }
            }
            Err(String::from("request failed"))
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            Err(String::from("request failed"))
        }
    }
}

pub async fn send_callback() -> Result<bool, String> {
    let user = global::BZ_USER.get().unwrap();
    let payload = json!({"token": user.token});

    info!("get send list request: {payload:#?}");

    match post("/mini/send/sendCallBack", &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<i32> = resp.json().await.unwrap();
                if response.code == 1 {
                    return Ok(true);
                } else {
                    return Err(response.msg);
                }
            }
            Err(String::from("request failed"))
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            Err(String::from("request failed"))
        }
    }
}
